from jili.core.printlog import print
from jili.price.ta import creat_ta_calcor
from research.calcor.calcor_logic import logic_calc, logic_calc_dict, logic_calc_df
from jili.core import get_models
from copy import deepcopy
import pandas as pd
import numpy as np
from jili.tool.convert import str2datetime
import talib
#支持三种类型  TA   function  logic
"""as 
calc_cmd:ta，function,logic
一、TA：符合TA算子规范的
    输入输出支持 A.B.C复杂数据索引
    区别ondata与onbar
    增加自定TA算子（只支持数据流模式）
二、function:1)直接返回值，2）返回字典
    参数规范参照TA的 支持 （） [],{}入参定义，支持（），[],{}出参定义
    基本涵盖了任意函数
    {'calc_cmd': 'function', 'function': XXX, 'out': ['real'], 'input': {'price': 'close'}}
    {'calc_cmd': 'function', 'function': XXX, 'out': {}, 'input': ['close','open']}}
    {'calc_cmd': 'function', 'function': XXX, 'out': ('real'), 'input': ('close','open')}}
    支持function 使用字符串name
    input: _:不索引
    增加支持 自动引用初始化class
    {'calc_cmd': 'class', 'class': "XXX","init_arg":{类初始化参数}, 'out': ('real'), 'input': ('close','open')}}
    默认找："research.calcor" 路径，也可以指定  modelname 优先寻找这里的
三、logic：1）标准logic  返回后直接定值
1.普通型：{'calc_cmd': 'logic', 'logic': {"and": {"test_f": {">": 1}, "test_f": {"<=": 10000}}},
         'out': ["test_logic"], 'value': [1, 0]}
2.复杂性：{'calc_cmd': 'logic', 'logic': {"and": {"test_f.a": {">": "test_f.b"}, "test_f": {"<=": 10000}}},
         'out': ["test_logic"], 'value': [1, 0]}
         
    支持 A.B.C复杂数据索引
    支持value 二元赋值
    支持 对比值也是一个索引
3.out _ 不返回值

graph_calcor_bypos：
1.入参增加pos
2.如果不存在则不计算

自定义模块中的算子：
只一个的话：算子配置中  使用：modelname
如果是多个的话：使用初始化参数：,class_url=[],function_url=[]
"""
def getdata(data, key):
    if "." in key:
        for i in key.split("."):
            if i in data.keys():
                data = data[i]
            else:
                return None
        return data
    else:
        if key == "_":
            return data
        else:
            return data[key]


def setdata(data, t):
    for k, v in t.items():
        if "." in k:
            d = data
            l = k.split(".")
            n = len(l)
            nn = 0
            for i in l:
                nn = nn + 1
                if nn < n:
                    if i not in d.keys():
                        d[i] = {}
                    d = d[i]
                else:
                    d[i] = v
        else:
            data[k] = v
    return data


def setdata1(data, t, o):
    for k, v in o.items():
        if "." in v:
            d = data
            l = v.split(".")
            n = len(l)
            nn = 0
            for i in l:
                nn = nn + 1
                if nn < n:
                    if i not in d.keys():
                        d[i] = {}
                    d = d[i]
                else:
                    if k in t.keys():
                        d[i] = t[k]
                    else:
                        d[i] = None
        else:
            if k in t.keys():
                data[v] = t[k]
            else:
                data[v] = None
    return data


def setdata0(data, k, v):
    if "." in k:
        d = data
        l = k.split(".")
        n = len(l)
        nn = 0
        for i in l:
            nn = nn + 1
            if nn < n:
                if i not in d.keys():
                    d[i] = {}
                d = d[i]
            else:
                d[i] = v
    else:
        data[k] = v
    return data
def update_out(b,r,cc,prex=None):
    if "out" in cc.keys():
        o=cc["out"]
        if r   is None:
            t = {}
            for k in o:
                if prex:
                    k=k+"_"+prex
                t[k] = None
        else:
            if not (isinstance(r,list) or isinstance(r,tuple)):
                r=[r]
            if prex:
                t = {k+"_"+prex: v for k, v in zip(o, r)}
            else:
                t = {k: v for k, v in zip(o, r)}
        b=setdata(b,t)
    return b
def update_out0(b,r,out,prex=None):
    o=out
    if r   is None:
        t={}
        for k in o:
            t[k]=None
    else:
        if not (isinstance(r,list) or isinstance(r,tuple)):
            r=[r]
        if prex:
            t = {k+"_"+prex: v for k, v in zip(o, r)}
        else:
            t = {k: v for k, v in zip(o, r)}
    b=setdata(b,t)
    return b
def drop_duplicate_calcors(cc):
    keys=[]
    c=[]
    for i in cc:
        k=i["out"]
        if k not in keys:
            c.append(i)
            keys.append(k)
    return c
class graph_calcor:
    def __init__(self,calcors,obj="",calcor_url=[],ispass_conlimit=False):
        self.class_model = get_models("research.calcor", path_depth=4, model_type="class", included__init__=False)
        self.function_model = get_models("research.calcor", path_depth=4, model_type="function", included__init__=False)
        for i in calcor_url:
            r=get_models(i, path_depth=4, model_type="class", included__init__=False)
            self.class_model.update(r)
            r = get_models(i, path_depth=4, model_type="function", included__init__=False)
            self.function_model.update(r)
        self.calcors_f = []
        self.obj=obj
        self.ispass_conlimit=ispass_conlimit
        if ispass_conlimit:
            self.onbar=self.onbar_1
            self.pre_data={}
            self.islimit_flag=0
        else:
            self.onbar=self.onbar_0
        self.set_calcors(calcors)

    # def __getstate__(self):
    #     # 返回对象的状态字典，该字典可以被pickle
    #     self.drop_ta()
    #
    # def __setstate__(self):
    #     self.init_ta()

    # def __serialize__(self):
    #     """自定义序列化方法"""
    #     self.drop_ta()
    #     return self
    #
    # def __deserialize__(self, data):
    #     """自定义反序列化方法"""
    #     self.init_ta()
    #     return self
    #
    # def __reduce__(self):
    #     """实现该魔术方法以使用自定义序列化方法"""
    #     return self.__serialize__, (self.data,)
    def drop_ta(self):#_thread._local问题;只是为了  策略的 save与load  算子的save与load
        if talib.__version__>"0.4.24":
            print("graph_calcor drop_ta")
            for i in self.calcors_f:
                if i["calc_cmd"]=="ta":
                    i["f"].drop_ta()
    def init_ta(self,isforce=True):#_thread._local问题
        if isforce:
            print("graph_calcor init_ta isforce")
            for i in self.calcors_f:
                if i["calc_cmd"] == "ta":
                    i["f"].init_ta(isforce)
        else:
            if talib.__version__>"0.4.24":
                print("graph_calcor init_ta")
                for i in self.calcors_f:
                    if i["calc_cmd"]=="ta":
                        i["f"].init_ta(isforce)

    def set_calcors(self,calcors):
        for ix in calcors:
            if ix["calc_cmd"] in ["function","logic"]:
                i=ix
            else:
                i=deepcopy(ix)
            if "start" in i.keys():
                i["start"]=str2datetime(i["start"])
            i["obj"]=self.obj
            if i["calc_cmd"] == "ta":
                if "outall" in i.keys():
                    i["outall"]=True
                tai=deepcopy(i)#i是按obj的算子，tai是ta的参数，避免无限引用
                f = creat_ta_calcor(tai,self.obj)
                i["f"] = f
            elif i["calc_cmd"] == "class":
                name=i["class"]
                if isinstance(name,str):
                    if "modelname" not in i.keys():
                        ss=self.class_model[name]
                    else:
                        class_f0=get_models(i["modelname"], path_depth=2, model_type="class", included__init__=False)
                        ss=class_f0[name]
                else:
                    ss=name
                init_args=i.get("init_args")
                if init_args is not None:
                    f=ss(**i["init_args"])
                else:
                    f = ss()
                i["function"]=f.oncalc
                i["instance"]=f
            elif i["calc_cmd"] == "function":
                key=i["function"]
                if isinstance(key,str):
                    if "modelname" not in i.keys():
                        ff = self.function_model[key]
                    else:
                        class_finction_ff0 = get_models(i["modelname"], path_depth=2, model_type="function", included__init__=False)
                        ff = class_finction_ff0[key]
                    i["function"]=ff
            self.calcors_f.append(i)
    def getdata(self,data,key):
        if "." in key:
            for i in key.split("."):
                if i in data.keys():
                    data=data[i]
                else:
                    return None
            return data
        else:
            if key == "_":
                return data
            else:
                return data[key]
    def setdata(self,data,t):
        for k, v in t.items():
            if "." in k:
                d = data
                l = k.split(".")
                n = len(l)
                nn = 0
                for i in l:
                    nn = nn + 1
                    if nn < n:
                        if i not in d.keys():
                            d[i] = {}
                        d = d[i]
                    else:
                        d[i] = v
            else:
                data[k] = v
        return data
    def setdata1(self,data,t,o):
        for k,v in o.items():
            if "." in v:
                d = data
                l = v.split(".")
                n = len(l)
                nn = 0
                for i in l:
                    nn = nn + 1
                    if nn < n:
                        if i not in d.keys():
                            d[i] = {}
                        d = d[i]
                    else:
                        if k in t.keys():
                            d[i] = t[k]
                        else:
                            d[i] = None
            else:
                if k in t.keys():
                    data[v] = t[k]
                else:
                    data[v] = None
        return data
    def setdata0(self,data,k,v):
        if "." in k:
            d = data
            l = k.split(".")
            n = len(l)
            nn = 0
            for i in l:
                nn = nn + 1
                if nn < n:
                    if i not in d.keys():
                        d[i] = {}
                    d = d[i]
                else:
                    d[i] = v
        else:
            data[k] = v
        return data
    def pdnan2None(self,v):
        if isinstance(v,dict):
            s = {}
            for k,i in v.items():
                s[k]=self.pdnan2None(i)
            return s
        elif isinstance(v,list):
            s=[]
            for i in v:
                s.append(self.pdnan2None(i))
            return s
        else:
            if pd.isna(v):
                return None
            else:
                return v
    def ondata(self,data,timekey=None):
        for i in self.calcors_f:
            if "start" in i.keys():
                if timekey:
                    if timekey<i["start"]:
                        continue
                # else:
                #     if data["timekey"]<i["start"]:
                #         continue
            cmd = i["calc_cmd"]
            if cmd == "ta":
                data = i["f"].ondata(data,timekey)
            elif cmd == "logic":
                r = logic_calc_dict(i["logic"], data)
                o = i["out"][0]
                if "value" in i.keys():
                    if r:
                        r = i["value"][0]
                    else:
                        r = i["value"][1]
                data=self.setdata0(data,o,r)
            elif cmd=="logic_stat":
                n=0
                r=i.get("default",None)
                for j in i["logic_stat"]:
                    r = logic_calc_dict(j, data)
                    if r:
                        r=i["value"][n]
                        break
                    n=n+1
                o = i["out"][0]
                data = self.setdata0(data, o, r)
            elif i["calc_cmd"] == "class":
                input = i.get("input")
                if input is not None:
                    if isinstance(input,dict):
                        args = {}
                        for k,v in input.items():
                            if v == "_":
                                args[k] = data
                            else:
                                args[k] = self.getdata(data,k)
                        args = self.pdnan2None(args)
                        r = i["function"](**args,timekey=timekey)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args,timekey=timekey)
                        else:
                            args = self.pdnan2None(self.getdata(data,input))
                            r = i["function"](args,timekey=timekey)
                    else:
                        args=[]
                        for k in input:
                            if k=="_":
                                args.append(data)
                            else:
                                args.append(self.getdata(data,k))
                        args = self.pdnan2None(args)
                        r = i["function"](*args,timekey=timekey)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args,timekey=timekey)
                o = i.get("out",{})
                if isinstance(o,dict):
                    if o:
                        data = self.setdata1(data, r,o)
                    else:
                        data=self.setdata(data,r)
                elif isinstance(o,str):
                    data = self.setdata0(data, o, r)
                elif isinstance(o,list) or isinstance(o,tuple):
                    data = update_out0(data, r, o)
                    # if len(o)==1:
                    #     k = o[0]
                    #     if isinstance(r,list):
                    #         data = self.setdata0(data, k,r[0])
                    #     else:
                    #         data = self.setdata0(data, k,r)
                    # else:
                    #     n=0
                    #     for k in o:
                    #         data = self.setdata0(data, k,r[n])
                    #         n=n+1
                else:
                    data = self.setdata(data, r)
            else:
                input = i.get("input")
                if input is not None:
                    if isinstance(input,dict):
                        args = {}
                        for k,v in input.items():
                            if v == "_":
                                args[k] = data
                            else:
                                args[k] = self.getdata(data,k)
                        args = self.pdnan2None(args)
                        r = i["function"](**args)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args)
                        else:
                            args = self.pdnan2None(self.getdata(data,input))
                            r = i["function"](args)
                    else:
                        args=[]
                        for k in input:
                            if k=="_":
                                args.append(data)
                            else:
                                args.append(self.getdata(data,k))
                        args = self.pdnan2None(args)
                        r = i["function"](*args)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args)
                o = i.get("out",{})
                if isinstance(o,dict):
                    if o:
                        data = self.setdata1(data, r,o)
                    else:
                        data=self.setdata(data,r)
                elif isinstance(o,str):
                    data = self.setdata0(data, o, r)
                elif isinstance(o,list) or isinstance(o,tuple):
                    data = update_out0(data, r, o)
                    # if len(o)==1:
                    #     k = o[0]
                    #     if isinstance(r,list):
                    #         data = self.setdata0(data, k,r[0])
                    #     else:
                    #         data = self.setdata0(data, k,r)
                    # else:
                    #     n=0
                    #     for k in o:
                    #         data = self.setdata0(data, k,r[n])
                    #         n=n+1
                else:
                    data = self.setdata(data, r)
        return data
    def onbar_0(self,data,timekey=None):
        for i in self.calcors_f:
            if "start" in i.keys():
                if data["timekey"]<i["start"]:
                    continue
            cmd=i["calc_cmd"]
            if cmd == "ta":
                data=i["f"].onbar(data,timekey)
            elif cmd=="logic":
                r=logic_calc_dict(i["logic"],data)
                o=i["out"][0]
                if "value" in i.keys():
                    if r:
                        r = i["value"][0]
                    else:
                        r = i["value"][1]
                data[o] = r
            elif cmd=="logic_stat":
                n=0
                r=i.get("default",None)
                for j in i["logic_stat"]:
                    r = logic_calc_dict(j, data)
                    if r:
                        r=i["value"][n]
                        break
                    n=n+1
                o = i["out"][0]
                data[o] = r
            elif i["calc_cmd"] == "class":
                input = i.get("input")
                if input is not None:
                    if isinstance(input, dict):
                        args = {}
                        for k, v in input.items():
                            if v=="_":
                                args[k] = data
                            else:
                                args[k] = data[v]
                        args=self.pdnan2None(args)
                        r = i["function"](**args,timekey=timekey)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args,timekey=timekey)
                        else:
                            args = self.pdnan2None(data[input])
                            r = i["function"](args,timekey=timekey)
                    elif isinstance(input, list):
                        if len(input)>1:
                            args = []
                            for k in input:
                                if k =="_":
                                    args.append(data)
                                else:
                                    args.append(data[k])
                            args = self.pdnan2None(args)
                            # args.append(timekey)
                            r = i["function"](*args,timekey=timekey)
                        else:
                            k=input[0]
                            if k=="_":
                                args = self.pdnan2None(data)
                                r = i["function"](args,timekey=timekey)
                            else:
                                # if k not in data.keys():
                                #     print("")
                                args = self.pdnan2None(data[k])
                                r = i["function"](args,timekey=timekey)
                    else:
                        print("err","错误的参数：",input)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args,timekey=timekey)
                o = i.get("out", {})#是否保留支持
                if isinstance(o, dict):
                    if o:
                        for k,v in o.items():
                            if k in r.keys():
                                data[v]=r[k]
                            else:
                                data[v] =None
                    else:
                        data.update(r)
                elif isinstance(o, str):
                    data[o] = r
                elif isinstance(o, list) or isinstance(o, tuple):
                    data=update_out0(data,r,o)
                    # if len(o)==1:
                    #     if isinstance(r,list):
                    #         k=o[0]
                    #         data[k]=r[0]
                    #     else:
                    #         k = o[0]
                    #         data[k] = r
                    # else:
                    #     n = 0
                    #     for k in o:
                    #         data[k] = r[n]
                    #         n = n + 1
                else:
                    if isinstance(r, list):
                        data[o] = r[0]
                    if isinstance(r, dict):
                        data.update(r)
                    else:
                        k = o
                        data[k] = r
            else:
                input = i.get("input")
                if input is not None:
                    if isinstance(input, dict):
                        args = {}
                        for k, v in input.items():
                            if v=="_":
                                args[k] = data
                            else:
                                args[k] = data[v]
                        args=self.pdnan2None(args)
                        r = i["function"](**args)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args)
                        else:
                            args = self.pdnan2None(data[input])
                            r = i["function"](args)
                    elif isinstance(input, list):
                        if len(input)>1:
                            args = []
                            for k in input:
                                if k =="_":
                                    args.append(data)
                                else:
                                    args.append(data[k])
                            args = self.pdnan2None(args)
                            r = i["function"](*args)
                        else:
                            k=input[0]
                            if k=="_":
                                args = self.pdnan2None(data)
                                r = i["function"](args)
                            else:
                                # if k not in data.keys():
                                #     print("")
                                args = self.pdnan2None(data[k])
                                r = i["function"](args)
                    else:
                        print("err","错误的参数：",input)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args)
                o = i.get("out", {})#是否保留支持
                if isinstance(o, dict):
                    if o:
                        for k,v in o.items():
                            if k in r.keys():
                                data[v]=r[k]
                            else:
                                data[v] =None
                    else:
                        data.update(r)
                elif isinstance(o, str):
                    data[o] = r
                elif isinstance(o, list) or isinstance(o, tuple):
                    data=update_out0(data,r,o)
                    # if len(o)==1:
                    #     if isinstance(r,list):
                    #         k=o[0]
                    #         data[k]=r[0]
                    #     else:
                    #         k = o[0]
                    #         data[k] = r
                    # else:
                    #     n = 0
                    #     for k in o:
                    #         data[k] = r[n]
                    #         n = n + 1
                else:
                    if isinstance(r, list):
                        data[o] = r[0]
                    if isinstance(r, dict):
                        data.update(r)
                    else:
                        k = o
                        data[k] = r
        return data
    def onbar_1(self,data,timekey=None):
        if self.pre_data:
            if data["open"]==data["close"]==data["high"]==data["low"]==self.pre_data["close"]:
                self.islimit_flag=self.islimit_flag+1
            else:
                self.islimit_flag=0
        for i in self.calcors_f:
            start=i.get("start")
            if start is not None:
                if data["timekey"]<start:
                    continue
            cmd=i["calc_cmd"]
            ispass_conlimit=i.get("ispass_conlimit",False)
            if ispass_conlimit and self.islimit_flag>2:
                o=i["out"]
                if isinstance(o,str):
                    data[o]=self.pre_data.get(o)
                else:
                    for k in o:
                        data[k]=self.pre_data.get(k)
                continue
            if cmd == "ta":
                data=i["f"].onbar(data,timekey)
            elif cmd=="logic":
                r=logic_calc_dict(i["logic"],data)
                o=i["out"][0]
                if "value" in i.keys():
                    if r:
                        r = i["value"][0]
                    else:
                        r = i["value"][1]
                data[o] = r
            elif cmd=="logic_stat":
                n=0
                r=i.get("default",None)
                for j in i["logic_stat"]:
                    r = logic_calc_dict(j, data)
                    if r:
                        r=i["value"][n]
                        break
                    n=n+1
                o = i["out"][0]
                data[o] = r
            elif i["calc_cmd"] == "class":
                input = i.get("input")
                if input is not None:
                    if isinstance(input, dict):
                        args = {}
                        for k, v in input.items():
                            if v=="_":
                                args[k] = data
                            else:
                                args[k] = data[v]
                        args=self.pdnan2None(args)
                        r = i["function"](**args,timekey=timekey)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args,timekey=timekey)
                        else:
                            args = self.pdnan2None(data[input])
                            r = i["function"](args,timekey=timekey)
                    elif isinstance(input, list):
                        if len(input)>1:
                            args = []
                            for k in input:
                                if k =="_":
                                    args.append(data)
                                else:
                                    args.append(data[k])
                            args = self.pdnan2None(args)
                            # args.append(timekey)
                            r = i["function"](*args,timekey=timekey)
                        else:
                            k=input[0]
                            if k=="_":
                                args = self.pdnan2None(data)
                                r = i["function"](args,timekey=timekey)
                            else:
                                # if k not in data.keys():
                                #     print("")
                                args = self.pdnan2None(data[k])
                                r = i["function"](args,timekey=timekey)
                    else:
                        print("err","错误的参数：",input)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args,timekey=timekey)
                o = i.get("out", {})#是否保留支持
                if isinstance(o, dict):
                    if o:
                        for k,v in o.items():
                            if k in r.keys():
                                data[v]=r[k]
                            else:
                                data[v] =None
                    else:
                        data.update(r)
                elif isinstance(o, str):
                    data[o] = r
                elif isinstance(o, list) or isinstance(o, tuple):
                    data=update_out0(data,r,o)
                    # if len(o)==1:
                    #     if isinstance(r,list):
                    #         k=o[0]
                    #         data[k]=r[0]
                    #     else:
                    #         k = o[0]
                    #         data[k] = r
                    # else:
                    #     n = 0
                    #     for k in o:
                    #         data[k] = r[n]
                    #         n = n + 1
                else:
                    if isinstance(r, list):
                        data[o] = r[0]
                    if isinstance(r, dict):
                        data.update(r)
                    else:
                        k = o
                        data[k] = r
            else:
                input = i.get("input")
                if input is not None:
                    if isinstance(input, dict):
                        args = {}
                        for k, v in input.items():
                            if v=="_":
                                args[k] = data
                            else:
                                args[k] = data[v]
                        args=self.pdnan2None(args)
                        r = i["function"](**args)
                    elif isinstance(input, str):
                        if input=="_":
                            args = self.pdnan2None(data)
                            r = i["function"](args)
                        else:
                            args = self.pdnan2None(data[input])
                            r = i["function"](args)
                    elif isinstance(input, list):
                        if len(input)>1:
                            args = []
                            for k in input:
                                if k =="_":
                                    args.append(data)
                                else:
                                    args.append(data[k])
                            args = self.pdnan2None(args)
                            r = i["function"](*args)
                        else:
                            k=input[0]
                            if k=="_":
                                args = self.pdnan2None(data)
                                r = i["function"](args)
                            else:
                                # if k not in data.keys():
                                #     print("")
                                args = self.pdnan2None(data[k])
                                r = i["function"](args)
                    else:
                        print("err","错误的参数：",input)
                else:
                    args = self.pdnan2None(data)
                    r = i["function"](args)
                o = i.get("out", {})#是否保留支持
                if isinstance(o, dict):
                    if o:
                        for k,v in o.items():
                            if k in r.keys():
                                data[v]=r[k]
                            else:
                                data[v] =None
                    else:
                        data.update(r)
                elif isinstance(o, str):
                    data[o] = r
                elif isinstance(o, list) or isinstance(o, tuple):
                    data=update_out0(data,r,o)
                    # if len(o)==1:
                    #     if isinstance(r,list):
                    #         k=o[0]
                    #         data[k]=r[0]
                    #     else:
                    #         k = o[0]
                    #         data[k] = r
                    # else:
                    #     n = 0
                    #     for k in o:
                    #         data[k] = r[n]
                    #         n = n + 1
                else:
                    if isinstance(r, list):
                        data[o] = r[0]
                    if isinstance(r, dict):
                        data.update(r)
                    else:
                        k = o
                        data[k] = r
        self.pre_data=data
        return data
class graph_calcor_axis1_fx_detail(graph_calcor):
    def ondata(self,data):
        return self.onbar(data)
    def onbar_0(self,data,timekey=None):
        return self.onbar_iml(data)
    def onbar_1(self,data,timekey=None):
        return self.onbar_iml(data)
    def onbar_iml(self,data):#data要求：自带key的 dict
        detail={}
        n=1
        for i in self.calcors_f:
            cmd=i["calc_cmd"]
            in_isdf=i.get("in_isdf",True)
            out_isdf=i.get("out_isdf",True)
            name=i.get("name",n)
            if in_isdf:
                if not isinstance(data,pd.DataFrame):
                    data=pd.DataFrame(data).T
                    # data=data.fillna(np.nan)
            else:
                if isinstance(data,pd.DataFrame):
                    data=data.to_dict("index")
            if cmd=="logic":
                if in_isdf:
                    r = logic_calc_df(i["logic"], data)
                    data=r
                else:
                    data0={}
                    for obj,v in data.items():
                        r=logic_calc_dict(i["logic"],data)
                        if r:
                            data0[obj]=v
                    data=data0
                detail[name]={"hold_n":len(data),"hold_data":deepcopy(data)}
            else:
                if in_isdf:
                    d=data
                    input = i.get("input")
                    if input is not None:
                        input=i["input"]
                        if len(input)==1:
                            d = data.loc[:, input[0]]
                        else:
                            d=data.loc[:,input]
                    r = i["function"](d)
                    data.loc[:, i["out"]]=r
                else:
                    o = i["out"][0]
                    r = i["function"](data)
                    for k,v in r.items():
                        data[k][o]=v
            n=n+1
        if out_isdf:
            if not isinstance(data, pd.DataFrame):
                data = pd.DataFrame(data).T
        else:
            if isinstance(data, pd.DataFrame):
                data = data.to_dict("index")

        return data,detail
class graph_calcor_axis1(graph_calcor):#增加属性；in_isdf;out_isdf
    def ondata(self,data):
        return self.onbar(data)

    def onbar_0(self, data, timekey=None):
        return self.onbar_iml(data)

    def onbar_1(self, data, timekey=None):
        return self.onbar_iml(data)

    def onbar_iml(self, data):  # data要求：自带key的 dict
        for i in self.calcors_f:
            cmd=i["calc_cmd"]
            in_isdf=i.get("in_isdf",True)
            out_isdf=i.get("out_isdf",True)
            if in_isdf:
                if not isinstance(data,pd.DataFrame):
                    data=pd.DataFrame(data).T
                    # data=data.fillna(np.nan)
            else:
                if isinstance(data,pd.DataFrame):
                    data=data.to_dict("index")
            if cmd=="logic":
                iscut=i.get("iscut",False)
                if in_isdf:
                    r = logic_calc_df(i["logic"], data)
                    if iscut:
                        data=r
                    else:
                        data.loc[:,i["out"]]=False
                        data.loc[r.index,i["out"]]=True
                else:
                    o = i["out"][0]
                    if iscut:
                        data0={}
                        for obj,v in data.items():
                            r=logic_calc_dict(i["logic"],data)
                            if r:
                                data0[obj]=v
                        data=data0
                    else:
                        for v in data.values():
                            r=logic_calc_dict(i["logic"],data)
                            v[o]=r
            else:
                if in_isdf:
                    d=data
                    input = i.get("input")
                    if input is not None:
                        input=i["input"]
                        if len(input)==1:
                            d = data.loc[:, input[0]]
                        else:
                            d=data.loc[:,input]
                    r = i["function"](d)
                    data.loc[:, i["out"]]=r
                else:
                    o = i["out"][0]
                    r = i["function"](data)
                    for k,v in r.items():
                        data[k][o]=v
        if out_isdf:
            if not isinstance(data, pd.DataFrame):
                data = pd.DataFrame(data).T
        else:
            if isinstance(data, pd.DataFrame):
                data = data.to_dict("index")
        return data


def f_test(data):
    return data["open"]

if __name__ == '__main__':
    # calors=[
    #     {'calc_cmd': 'ta', 'cmd': 'OBV', 'out': ['OBV'], 'input': {'price': 'close', 'prices': ['volume']}, 'arg': {},
    #      'batch': 1},
    #     {'calc_cmd': 'function', 'function': f_test,'out':['test_f']},
    #     {'calc_cmd': 'logic', 'logic': {"and": {"test_f": {">": 1}, "test_f": {"<=": 10000}}},
    #      'out': ["test_logic"], 'value': [1, 0]}
    # ]
    # from jili.core import load
    # k=load(r"E:\data\k1m\TA905_k1m.pkl")
    # g=graph_calcor(calors)
    # for i in k:
    #     t=g.ondata(i["timekey"],i)
    #     print(t)
    arg = [0, 5, 60, 242, 0.1, 0.5, 242, 30]
    calcors_config = [  # 计算obj k1m周期的因子或算子并并入k1m数据体
        {'calc_cmd': 'ta', 'cmd': 'MA', 'out': ["MA5"], 'input': {'price': 'close'},
         'arg': {'timeperiod': arg[1], 'matype': arg[0]}, 'batch': arg[1]},
        {'calc_cmd': 'ta', 'cmd': 'MA', 'out': ["MA60"], 'input': {'price': 'close'},
         'arg': {'timeperiod': arg[2], 'matype': arg[0]}, 'batch': arg[2]},
        {'calc_cmd': 'ta', 'cmd': 'DIV', 'out': ['MA5_MA60'], 'input': {'price0': 'MA5', 'price1': 'MA60'},
         'arg': {}, 'batch': 1},
        {'calc_cmd': 'ta', "cmd": "fenweishu", "out": ["score"], "arg": {"timeperiod": arg[3]},
         "input": ["close"]},
        # 标准化
        {'calc_cmd': 'ta', 'cmd': 'STDDEV', 'out': ["r1"], 'input': {'price': 'close'},
         'arg': {'timeperiod': arg[6], 'nbdev': 1.0}, 'batch': arg[6]},
        {'calc_cmd': 'ta', 'cmd': 'STDDEV', 'out': ["r2"], 'input': {'price': 'close'},
         'arg': {'timeperiod': arg[7], 'nbdev': 1.0}, 'batch': arg[7]},
    ]
    f = graph_calcor(calcors_config)
    f1 = graph_calcor(calcors_config)
    f2= graph_calcor(calcors_config)
    f3 = graph_calcor(calcors_config,"3")
    f4 = graph_calcor(calcors_config,"4")
    print(f1.calcors_f[0]["f"] == f2.calcors_f[0]["f"])
    print(
        f1.calcors_f[0]["f"] == f2.calcors_f[0]["f"] == f.calcors_f[0]["f"])
    print(f1.calcors_f[0]["f"]==f2.calcors_f[0]["f"]==f.calcors_f[0]["f"]==f3.calcors_f[0]["f"]==f4.calcors_f[0]["f"])

